home *** CD-ROM | disk | FTP | other *** search
Makefile | 1991-06-28 | 12.4 KB | 380 lines |
- #******************************************************************************
- # This GNUmakefile is useful for large and complex projects which involve
- # both G++ library prototypes, and prototypes added by the user(s). It
- # is assumed that certain conventions are followed.
- #
- # 1) each object has its own source and header files. For example class W
- # would have W.h and W.cc
- #
- # 2) each prototype object has its own source and header files (W.hP and W.ccP)
- #
- # 3) object header files are contained in directory $(IDIR) (for Include
- # DIRectory)
- #
- # 4) object source files are contained in the current directory
- #
- # 5) prototype instantiations are contained in $(PC) (for Prototype C++
- # directory)
- #
- # 6) user prototype files (both header and source) are contained in $(IPP)
- #
- # 7) non-class code is contained in .h and .cc files, which live in $(IDIR)
- # and the current directory respectively
- #
- # *) as an extra, I have added the convention that whenever a W.cc file
- # is being compiled, the macro _W_cc is defined. This is useful
- # particularly for conditional parts of header files (for example,
- # W.h could have ifdef _W_cc ...
- #
- # The makefile works in the following manner: the source dependencies are
- # contained in .Makefile.S_DEP, while the (machine generated) object
- # dependencies are contained in .Makefile.O_DEP. The types needed by
- # the program are defined by several variables, and the makefile generates
- # the necessary dependencies (both source and object) from those variables.
- # The prototype lists are contained in .Makefile.TYPES.
- #
- # NOTE: in order to create the machine generated files .Makefile.TYPES,
- # .Makefile.S_DEP, and .Makefile.O_DEP, empty versions of these
- # file must exist. They can be easily created using "touch <file>".
- #
- # -- Carl Staelin
- # staelin@princeton.edu
- #******************************************************************************
-
- #******************************************************************************
- # standard Makefile definitions
-
- comma := ,
- space := $(empty) $(empty)
- tab := $(empty) $(empty)
-
- #******************************************************************************
- # definitions from environment variables
-
- # the CPATH include directories
- cpath-include-directories := $(addprefix -I, $(subst :,$(space),$(CPATH)))
-
- # the LPATH load directories
- lpath-load-directories := $(addprefix -L, $(subst :,$(space),$(LPATH)))
-
- #******************************************************************************
- # Basic definitions
-
- HOST := $(shell hostname)
-
- BASE :=
-
- # CMU Directories
- USR := $(BASE)/usr
- MACH := $(BASE)/usr/mach
- CS := $(BASE)/usr/cs
-
- # GNU directories
- GNULIBDIR := $(BASE)/usr/local/lib
- GNUIDIR := $(GNULIBDIR)/g++-include
-
- # the g++ library prototypes...
- LPP := $(GNUIDIR)
- PC := ../libg++
-
- # the user's library prototypes...
- IPP := ../proto
-
- # the include directory
- IDIR := ../include
-
- # the include directories needed...
- IDIRS := -I$(IDIR) -I$(PC) -I$(GNUIDIR) $(cpath-include-directories)
-
- # the directories where the libraries live...
- LDIRS := $(lpath-load-directories)
-
- #******************************************************************************
- # standard function (and associated variables) definitions
-
- C++ = g++
- C++FLAGS = -pipe -O $(IDIRS)
- -Dc_plusplus \
- -DDEBUG \
- -D$(strip $(subst .,_, _$(basename $(@F))_cc))
-
-
- GENCLASS = ../bin/genclass.extnsn
- PREPEND = ../bin/prepend
- HIERARCHY = ../bin/hierarchy
- MAKE_TYPES = ../bin/make-types
- PROTOTYPE = ../bin/prototype
-
- #******************************************************************************
- # implicit rules
-
- %.o : %.cc
- $(C++) $(C++FLAGS) \
- -c -o $@ $(@D)$(basename $(@F)).cc
-
- #******************************************************************************
- # User types
-
- BASIC_TYPES = \
- int \
- u_int \
- l_int \
- l_u_int
-
- # generated by this make file (initially create an empty .Makefile.TYPES
- # so that "make dependencies" can create the real file)
- include .Makefile.TYPES
-
- #******************************************************************************
- # User types (with sample values filled in)
- #
- # NOTE: do NOT add .h to the end of these, MAKE does it for you!
-
- HEADER_FILES = \
- disk_set \
- file_types \
- include \
- inode \
- inode_t \
- lib \
- main \
- nfs_functions \
- nfs_mount \
- nfs_params \
- nfs_prot \
- system
-
- SOURCE_FILES = \
- disk_set \
- lib \
- nfs_auxil \
- nfs_dirent \
- nfs_fh \
- nfs_ipcress \
- nfs_links \
- nfs_main \
- nfs_mnt_serv \
- nfs_mount_xdr \
- nfs_prot_xdr \
- nfs_serv1 \
- nfs_serv2 \
- nfs_serv3 \
- nfs_serv4 \
-
- #******************************************************************************
- # some sample machine generated user-file stuff
- #
- ../include/file_types.h : ../include/file_types.type.h ../include/file_types.operation.h
- ../include/Substrate_file.h : ../include/file_types.includes.h
-
- ../include/file_types.type.h : ../include/file_types.hierarchy
- $(HIERARCHY) -voutput_type=type ../include/file_types.hierarchy > $@
-
- ../include/file_types.includes.h : ../include/file_types.hierarchy
- $(HIERARCHY) -voutput_type=general -vpreamble='#include "' \
- -vpostamble='.h"' -vprint_first=1 ../include/file_types.hierarchy > $@
-
- ../include/file_types.operation.h : ../include/file_types.hierarchy
- (echo '#define FILE_TYPES_OPERATION(OPERATION) \' ; \
- $(HIERARCHY) -voutput_type=general -vpreamble='OPERATION(' \
- -vpostamble=') \' -vprint_first=1 ../include/file_types.hierarchy ; \
- echo ; ) | sed 's/\.//g' > $@ ;
-
- #******************************************************************************
- # source files...
-
- HEADERS := $(wildcard $(addprefix $(IDIR)/, $(addsuffix .h, $(USER_TYPES) $(HEADER_FILES))))
-
- SOURCES := $(wildcard $(addsuffix .cc, $(USER_TYPES) $(SOURCE_FILES)))
-
- OBJECTS := $(patsubst %.cc,%.o,$(SOURCES))
-
- #******************************************************************************
- # User prototype instantiations
-
- USER_PROTO_HEADERS := $(addprefix $(PC)/, $(addsuffix .h, $(foreach type, $(basename $(notdir $(wildcard $(addprefix $(IPP)/, $(addsuffix .hP, $(USER_BASE_PROTO_TYPES)))))), $(filter %.$(type), $(USER_PROTO_TYPES)))))
-
- USER_PROTO_SOURCES := $(addprefix $(PC)/, $(addsuffix .cc, $(foreach type, $(basename $(notdir $(wildcard $(addprefix $(IPP)/, $(addsuffix .ccP, $(USER_BASE_PROTO_TYPES)))))), $(filter %.$(type), $(USER_PROTO_TYPES)))))
-
- USER_PROTO_OBJECTS := $(patsubst %.cc, %.o, $(USER_PROTO_SOURCES))
-
- USER_PROTO_TYPE_SOURCES := $(wildcard $(addprefix $(IPP)/, $(addsuffix .hP, $(USER_BASE_PROTO_TYPES)) $(addsuffix .ccP, $(USER_BASE_PROTO_TYPES))))
-
- #******************************************************************************
- # libg++ prototype instantiations
-
- LIB_PROTO_HEADERS := $(addprefix $(PC)/, $(addsuffix .h, $(foreach type, $(basename $(notdir $(wildcard $(addprefix $(LPP)/, $(addsuffix .hP, $(LIB_BASE_PROTO_TYPES)))))), $(filter %.$(type), $(LIB_PROTO_TYPES)))))
-
- LIB_PROTO_SOURCES := $(addprefix $(PC)/, $(addsuffix .cc, $(foreach type, $(basename $(notdir $(wildcard $(addprefix $(LPP)/, $(addsuffix .ccP, $(LIB_BASE_PROTO_TYPES)))))), $(filter %.$(type), $(LIB_PROTO_TYPES)))))
-
- LIB_PROTO_OBJECTS := $(patsubst %.cc, %.o, $(LIB_PROTO_SOURCES))
-
- .PHONY : test
- test :
- @echo LIB_PROTO_TYPES = "${LIB_PROTO_TYPES}";
- @echo LIB_BASE_PROTO_TYPES = "${LIB_BASE_PROTO_TYPES}" ;
- @echo LIB_PROTO_OBJECTS = "${LIB_PROTO_OBJECTS}" ;
- @echo LIB_PROTO_HEADERS = "${LIB_PROTO_HEADERS}" ;
-
- #*****************************************************************************
- # main procedures..
-
- # example:
- foo : foo.o $(OBJECTS)
- $(C++) $(C++FLAGS) -o $@ foo.o $(OBJECTS) $(LDIRS)
-
- sources : $(SOURCES)
-
- #******************************************************************************
- # various cleanup stuff...
-
- .PHONY : rmback clean realclean
-
- rmback :
- cd .. ; rm -f proto/*~ include/*~ src/*~
-
- clean : rmback
- rm -f $(OBJECTS) $(PROTOLIB) $(LIB_PROTO_OBJECTS) $(USER_PROTO_OBJECTS)
-
- realclean : clean
- rm -f $(LIB_PROTO_SOURCES) $(USER_PROTO_SOURCES) $(LIB_PROTO_HEADERS) $(USER_PROTO_HEADERS)
-
-
- #*****************************************************************************
- # debugging actions
-
- %.E : %.cc
- $(C++) $(C++FLAGS) -E $(@D)$(basename $(@F)).cc > $@
-
- %.s : %.cc
- $(C++) -S $(C++FLAGS) $< -o $@
-
- #******************************************************************************
- # "functions" for creating library source code from prototypes
-
- parameters = $(subst .,$(space),$(notdir $(basename $(basename $@))))
- ifdef_filename = $(subst .,_,$(notdir $(basename $@)))
-
- generic-type = $(subst .,,$(suffix $(basename $(notdir $@))))
-
- #
- # return the type if it should be a "val" type (pointer or basic type)
- #
- parameter-val-q = $(filter %_p, $(parameter)) $(filter-out %_p, $(filter $(parameter), $(BASIC_TYPES)))
-
- #
- # return the list of pairs of types and their prototype type (val or ref)
- #
- proto-type-arg = $(parameter) \
- $(patsubst %, val, $(filter 1, $(words $(parameter-val-q)))) \
- $(patsubst %, ref, $(filter-out 1, $(words $(parameter-val-q))))
-
- define make-proto-file
- $(GENCLASS) \
- $(dir $<) \
- $(dir $@) \
- $(suffix $@) \
- $(foreach parameter, $(parameters), $(proto-type-arg)) \
- $(generic-type) ;
- endef
-
-
- define prepend-proto-includes
- $(PREPEND) \
- $(addsuffix .h, $(basename $@)) \
- '#include "include.h"' \
- $(patsubst %, '#include "%.h"', $(foreach type, $(USER_TYPES) $(USER_PROTO_TYPES) $(LIB_PROTO_TYPES), $(patsubst %, $(type), $(filter $(subst .,, $(type)), $(patsubst %_p, %, $(parameters)))))) ;
- endef
-
- #******************************************************************************
- # libg++ prototype dependencies
-
-
- #
- # Used to automatically generate a %_p.defs file, which is required by classes
- # which do comparisons, for pointer types to objects which have the real
- # comparison code.
- #
- # this will cat the appropriate strings
- #
- $(addprefix $(PC)/, $(addsuffix .h, $(filter-out char_p.defs, $(filter %_p.defs, $(LIB_PROTO_TYPES))))) :
- @ echo creating $@ ; \
- ( ifdef_filename=$(strip $(ifdef_filename)) \
- p=$(strip $(patsubst %_p, %, $(parameters))) \
- ../bin/make-defs-file ) > $@ ;
-
- lib_proto_intermediate_sources = \
- $(filter-out %_p.defs.h, $(LIB_PROTO_HEADERS) $(LIB_PROTO_SOURCES)) \
- $(addprefix $(PC)/, $(addsuffix .h, char_p.defs))
-
- lib_type_and_suffix_list = $(sort $(join $(suffix $(basename $(lib_proto_intermediate_sources))), $(addprefix ., $(suffix $(lib_proto_intermediate_sources)))))
-
- #******************************************************************************
- # prototype dependencies
-
- proto_intermediate_sources = \
- $(USER_PROTO_HEADERS) \
- $(USER_PROTO_SOURCES)
-
- type_and_suffix_list = $(sort $(join $(suffix $(basename $(proto_intermediate_sources))), $(addprefix ., $(suffix $(proto_intermediate_sources)))))
-
- #******************************************************************************
- # generate machine generated dependencies
-
- H_FILES = $(HEADERS) $(LIB_PROTO_HEADERS) $(USER_PROTO_HEADERS)
- CC_FILES = $(SOURCES) $(LIB_PROTO_SOURCES) $(USER_PROTO_SOURCES)
-
- DEPENDENCIES = $(addsuffix .d, $(basename $(CC_FILES)))
-
- $(addsuffix .d, $(basename $(CC_FILES))) : %.d : %.cc
- ( echo -n $(@D) ; $(C++) -M $(C++FLAGS) $*.cc) > $@;
-
- #******************************************************************************
- # machine generated type stuff
- #
-
- $(DEPENDENCIES) : $(H_FILES)
-
- .PHONY : dependencies source-dependencies object-dependencies
-
- dependencies : type-definitions source-dependencies
- @ $(MAKE) object-dependencies
-
- object-dependencies : $(DEPENDENCIES)
- @echo making object dependencies... ; \
- rm .Makefile.O_DEP ; \
- ls . | grep '\.d$$' > /tmp/dependencies ; \
- ls $(PC) | gawk '{printf "$(PC)/%s\n", $$0 ; }' | grep '\.d$$' >> \
- /tmp/dependencies ; \
- for file in `cat /tmp/dependencies` ; do \
- cat $$file ; \
- done > .Makefile.O_DEP.tmp ; \
- mv .Makefile.O_DEP.tmp .Makefile.O_DEP ; \
- for file in `cat /tmp/dependencies` ; do \
- rm $$file ; \
- done ; \
- rm /tmp/dependencies ;
-
-
- source-dependencies :
- @ echo making source dependencies... ; \
- ($(PROTOTYPE) -voutput_type=libg++-prototypes \
- ../include/prototype.dependencies | \
- gawk '($$1 !~ "_p.defs$$") || ($$1 == "char_p.defs") { print ; }' | \
- PROTO_SOURCE=$(LPP) PP=LPP ../bin/make-source-dependencies ; \
- ($(PROTOTYPE) -voutput_type=user-prototypes \
- ../include/prototype.dependencies ; \
- $(HIERARCHY) -voutput_type=general ../include/file_types.hierarchy) | \
- PROTO_SOURCE=$(IPP) PP=IPP ../bin/make-source-dependencies ; \
- ) > .Makefile.S_DEP ;
-
- type-definitions :
- @ echo make type definitions... ; \
- $(MAKE_TYPES) > .Makefile.TYPES ;
-
- #******************************************************************************
- # include machine generated dependencies
-
- include .Makefile.S_DEP
- include .Makefile.O_DEP
-